iT邦幫忙

2024 iThome 鐵人賽

DAY 16
1

Secret 是 Kubernetes 中的一種資源,用於存儲和管理敏感數據,如密碼、OAuth tokens、SSH keys 等。Secret 允許你將這些敏感信息安全地傳遞給應用程式,而不需要將它們硬編碼到容器映像或組態檔案中。

為什麼需要 Secret

將敏感信息存儲在 Secret 中而非硬編碼到應用程式中,可以帶來以下幾個好處:

  • 安全性:敏感數據可以使用 base64 編碼,並在必要時進行加密和保護,從而防止未經授權的訪問。
  • 集中管理:所有敏感信息都集中在 Secret 中,便於管理和更新,而不需要重新部署應用程式。
  • 環境分離:可以根據環境(開發、測試、生產)來區分和管理不同的敏感信息。

Secret 與 ConfigMap 的差別

  • 用途

    • ConfigMap 用於存儲非機密的配置數據(如環境變數、應用程式設定)。
    • Secret 用於存儲機密數據(如密碼、憑證、tokens)。
  • 安全性

    • ConfigMap 中的數據以明文形式存儲,對安全性要求不高。
    • Secret 中的數據以 base64 編碼形式存儲,並且可以使用 Kubernetes 內建的加密機制來保護數據的安全性。
  • 使用場景

    • ConfigMap 適用於一般的配置管理。
    • Secret 適用於需要保密的數據管理。

Secret 的類型

  1. Opaque:默認類型,用於存儲任意鍵值對。
  2. kubernetes.io/dockerconfigjson:用於存儲 Docker 的鏡像拉取密鑰(dockerconfig.json 文件)。
  3. kubernetes.io/service-account-token:存儲 Kubernetes ServiceAccount 的 token,通常由系統自動創建。
  4. kubernetes.io/tls:用於存儲 TLS/SSL 憑證,包括 .crt.key 文件。

應用場景

  1. 憑證管理:存儲和管理 TLS/SSL 憑證,並將它們注入到需要的容器中。
  2. 密碼管理:存儲資料庫密碼、API tokens 等敏感數據,並安全地傳遞給應用程式。
  3. SSH keys:將 SSH 密鑰存儲在 Secret 中,並用於安全地連接到其他服務或節點。

組態檔案說明

以下是一個使用 Secret 的 Kubernetes 組態檔範例:

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: dXNlcm5hbWU=  # "username" base64 編碼後的值
  password: cGFzc3dvcmQ=  # "password" base64 編碼後的值
  • typeOpaque 是鍵值類型,用於存儲任意類型的機密數據。
  • data:包含了 base64 編碼後的敏感數據。
    • usernamepassword 是存儲在 Secret 中的兩個鍵值對,分別代表 base64 編碼後的使用者名稱和密碼。

解碼後,username 的原始值是 "username"password 的原始值是 "password"

這個 Secret 可以用於應用程式中,通過環境變數或掛載到檔案的方式來安全地傳遞這些敏感數據。

實作

建立 Secret

這是實作要儲存的內容:

username=vincent
password=vincent_12345678
  • 使用以下指令,輸出 base64 加密後的 password
$ echo -n vincent_12345678 | base64 -w 0

說明:

-w 0 是為了避免額外的分段符號被選中加密

組態檔案: secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
stringData:
  username: vincent
data:
  password: dmluY2VudF8xMjM0NTY3OA==
  • 透過組態文件建立 secret
kubectl apply -f secret.yaml

或者也可以使用 kubectl create 指令建立 secret。好處是可以直接輸入明碼,不用事先加密值

  • 透過 kubectl create 建立 secret
kubectl create secret generic mysql-secret --from-literal='username=vincent' --from-literal='password=vincent_12345678'

驗證 Secret

儘管我們在 manifest 使用了 stringData 明碼輸入值,但使用 kubectl get 取得 mysql-secret 後,只剩下 data 欄位

kubectl get secrets mysql-secret -o yaml

結果如下

apiVersion: v1
items:
- apiVersion: v1
  data:
    password: dmluY2VudF8xMjM0NTY3OA==
    username: dmluY2VudA==
  kind: Secret
  metadata:
	[...]
    name: mysql-secret
    namespace: default
    resourceVersion: "163920"
    uid: c2d86028-dd87-4fc1-9cfb-e0cc7080e35b
  type: Opaque
kind: List
metadata:
  resourceVersion: ""
  • 使用 jsonpath 輸出 data 資訊,得到 base64 加密後的內容
kubectl get secrets mysql-secret -o jsonpath='{.data}'
---
{"password":"dmluY2VudF8xMjM0NTY3OA==","username":"dmluY2VudA=="}
  • 驗證 secrets 裡的內容
kubectl get secrets mysql-secret -o jsonpath='{.data.username}' | base64 -d
---
vincent
kubectl get secrets mysql-secret -o jsonpath='{.data.password}' | base64 -d
---
vincent_12345678

將 secrets 取得的值透過 base64 解碼後,與原始的資料相符

在 Pod 中使用 Secret

在 Pod 使用 Secret 資料的方法跟 ConfigMap 類似: 掛載為文件設為環境變量

掛載為文件 - 映射整個 secret

組態檔案: pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-container
    image: registry.k8s.io/busybox
    command: [ "/bin/sh", "-c", "sleep 3600" ]
    volumeMounts:
    - name: vol
      mountPath: "/mnt/data"
      readOnly: true
  volumes:
  - name: vol
    secret:
      secretName: mysql-secret
  • 部署 Pod
kubectl apply -f pod.yaml
  • 在 Pod 裡驗證
kubectl exec test-pod -- sh -c 'ls /mnt/data'
---
password
username
kubectl exec test-pod -- sh -c 'cat /mnt/data/password'
---
vincent_12345678
  • 刪除 pod
kubectl delete -f pod.yaml --now

掛載為文件 - 映射特定鍵到特定檔案

組態檔案: pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-container
    image: registry.k8s.io/busybox
    command: [ "/bin/sh", "-c", "sleep 3600" ]
    volumeMounts:
    - name: vol
      mountPath: "/mnt/data"
      readOnly: true
  volumes:
  - name: vol
    secret:
      secretName: mysql-secret
      items:
      - key: username
        path: my-group/my-username
  • 部署 Pod
kubectl apply -f pod.yaml
  • 在 Pod 裡驗證
kubectl exec test-pod -- sh -c 'cat /mnt/data/my-group/my-username'
---
vincent
  • 刪除 pod
kubectl delete -f pod.yaml --now

設為環境變量 - 映射整個 secret

組態檔案: pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-container
    image: registry.k8s.io/busybox
    command: [ "/bin/sh", "-c", "sleep 3600" ]
    envFrom:
    - secretRef:
        name: mysql-secret
  • 部署 Pod
kubectl apply -f pod.yaml
  • 在 Pod 裡驗證
kubectl exec -i -t test-pod -- sh -c 'echo $username $password'
---
vincent vincent_12345678
  • 刪除 pod
kubectl delete -f pod.yaml --now

設為環境變量- 映射特定鍵到特定檔案

組態檔案: pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
  - name: test-container
    image: registry.k8s.io/busybox
    command: [ "/bin/sh", "-c", "sleep 3600" ]
    env:
    - name: MYSQL_USERNAME
      valueFrom:
        secretKeyRef:
          name: mysql-secret
          key: username
  • 部署 Pod
kubectl apply -f pod.yaml
  • 在 Pod 裡驗證
kubectl exec -i -t test-pod -- sh -c 'echo $MYSQL_USERNAME'
---
vincent
  • 刪除 pod
kubectl delete -f pod.yaml --now

小結

Secret 提供了一種安全、集中化的方式來管理 Kubernetes 中的敏感資料,確保在應用程式部署過程中的資料安全性。與專注於一般配置管理的 ConfigMap 不同,Secret 著重於機密資訊的保護。

從功能和用途上看,Kubernetes 的 Secret 類似於 AWS 的 Secrets Manager,而 ConfigMap 則類似於 AWS Systems Manager Parameter Store。對這方面有興趣的朋友,可以從 AWS 相關服務的介紹開始深入了解。


上一篇
學 Kubernetes 的第十五天 - Storage - ConfigMap
下一篇
學 Kubernetes 的第十七天 - Storage - PV & PVC
系列文
都什麼年代了,還在學 Kubernetes37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言